package com.sduept.nwld.fault.outer.model.factory;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.StringUtils;

import com.sduept.bigdata.fault.entity.FaultRecord;
import com.sduept.bigdata.fault.entity.FaultReportMain;
import com.sduept.bigdata.fault.entity.FaultReportMainProtection;
import com.sduept.bigdata.fault.entity.FaultReportStationDetail;
import com.sduept.cim.model.core.Substation;
import com.sduept.cim.model.protection.ProtectionEquipment;
import com.sduept.cim.model.wires.ACLineSegment;
import com.sduept.nwld.fault.outer.model.FaultTripInfo;
import com.sduept.nwld.fault.outer.model.ProtectInfo;
import com.sduept.nwld.fault.outer.model.StationTripInfo;
import com.sduept.utils.DateUtil;


public class AclineOuterFaultModelFactory extends AbstractOuterFaultModelFactory{
	private static final String head_template="#{station}报#{devicename}保护动作情况：\n";
	private static final String acline_body_template="#{protect}#{componet}动作，选#{phase}相，测距#{distance}km，\n";
	private static final String acline_footer_template="行波测距#{travellingwave}km，故障录波测距#{rangingwave}km，重合闸#{reclose}。";
	
	private static AclineOuterFaultModelFactory factory = new AclineOuterFaultModelFactory();
	private AclineOuterFaultModelFactory(){}
	public static AbstractOuterFaultModelFactory getInstance(){
		return factory;
	}
	/**
	 * @param model
	 * @return
	 * @throws Exception
	 */
	@Override
	public  FaultTripInfo getFaultTripInfo(FaultRecord record)throws Exception{
		int count=0;
		List<FaultReportMain> mains  = superDao.findByCondition(FaultReportMain.class, "faultRecord.id=?", record.getId());
		//由于故障报告存储有滞后性，该方法拦截的是故障记录存储，可能在调用的时候没有生成故障报告，因此加入
		//自旋等待。保证故障报告能取到
		while(mains.size()==0 && count<5){
			Thread.sleep(5*1000);
			count++;
			mains  = superDao.findByCondition(FaultReportMain.class, "faultRecord.id=?", record.getId());
		}
		if(mains.size()>0) {
			return buildFaultTripInfo(record,mains.get(0));
		}
		return null;
	}
	
	private FaultTripInfo buildFaultTripInfo(FaultRecord record,FaultReportMain main){
		FaultTripInfo result = new FaultTripInfo();
		String devcieName = record.getEquipment();
		String deviceId = record.getEquipment_id();
		result.setId(record.getId());
		result.setStatus(record.getStatus());
		ACLineSegment line = cm.getAcLineSegmentById(record.getEquipment_id());
		if(line!=null){
			result.setDeviceRdfId(line.getRdfId());
			result.setDeviceGid(line.getId());
		}
		result.setFaultDate(record.getFaultTime().getTime());
		result.setFaultPhase(record.getFaultPhase());
		result.setDeviceName(devcieName);
		StationTripInfo sti = null;
		Double startStationDistance = main.getDoubleResult();
		Double endStationDistance = null;
		for(FaultReportStationDetail sdetail: main.getFaultReportStationDetails()){
			sti  = buildStationTripInfo(record.getFaultTime(),devcieName, deviceId,sdetail);
			if(StringUtils.isNotEmpty(sti.getRecolse())){
				result.setRecolse(sti.getRecolse());
			}
			result.getStationTripInfos().add(sti);
			if(StringUtils.isNotEmpty(sdetail.getStationId()) &&sdetail.getStationId().equals(record.getStationId()) 
					&& sdetail.getTravelingWave()!=null && sdetail.getTravelingWave()>0){
				startStationDistance = sdetail.getTravelingWave();
			}else if(StringUtils.isNotEmpty(sdetail.getStationId()) && sdetail.getStationId().equals(record.getStationId2())
					&& sdetail.getTravelingWave()!=null && sdetail.getTravelingWave()>0){
				endStationDistance = sdetail.getTravelingWave();
			}
		}
		//设置跳闸事件
		StringBuilder sb = new StringBuilder(DateUtil.getStringDate(new Date(result.getFaultDate()), DateUtil.pattern_ymdhm)+"，"+devcieName);
		if(StringUtils.isNotEmpty(result.getFaultPhase())){
			sb.append("，"+result.getFaultPhase());
		}
		sb.append("相跳闸");
		if(StringUtils.isNotEmpty(result.getRecolse())){
			sb.append("，重合闸"+result.getRecolse());
		}
		result.setTripName(sb.toString());
		// 设置故障分析信息
		StringBuilder faultAnlysis =  new StringBuilder();
		String iceAnlysisInfo  = wdm.getNewFaultIceInfo(record);
		if(StringUtils.isNotEmpty(iceAnlysisInfo)){
			faultAnlysis.append(iceAnlysisInfo+"\n");
		}
		String thunderAnlysisInfo  = wdm.getNewFaultThunderInfo(record);
		if(StringUtils.isNotEmpty(thunderAnlysisInfo)){
			faultAnlysis.append(thunderAnlysisInfo);
		}
		if(StringUtils.isNotEmpty(faultAnlysis.toString())){
			result.setFaultAnlysis(faultAnlysis.toString());
		}
		//设置天气情况
		Integer tower = null;
		if(startStationDistance!=null && startStationDistance>0){
			tower = fam.getTowerNo(startStationDistance, null, deviceId);
		}else if(endStationDistance!=null && endStationDistance>0){
			tower = fam.getTowerNo(null, endStationDistance, deviceId);
		}
		if(tower!=null){
			String weather = wm.findWeatherByTower(deviceId, tower, record.getFaultTime());
			for(StationTripInfo st:result.getStationTripInfos()){
				st.setWeather(weather);
			}
		}
		return result;
	}
	/**
	 * 构建变电站跳闸信息
	 * @param smodel
	 * @param pmodel
	 * @return
	 */
	private StationTripInfo buildStationTripInfo(Date faultTime,String deviceName,String deviceId,FaultReportStationDetail sdetail){
		StationTripInfo result = new StationTripInfo();
		if(StringUtils.isNotEmpty(sdetail.getStationId())){
			Substation station =  cm.getStationById(sdetail.getStationId());
			if(station!=null){
				result.setStationRdfId(station.getRdfId());
				result.setStationGid(station.getId());
			}
		}
		result.setStationName(sdetail.getStationName());
		if(sdetail.getManualRangingWave()!=null && sdetail.getManualRangingWave()>0){
			double df = getNeededPrecisionNumber(sdetail.getManualRangingWave()); 
			result.setRangingWave(df);
		}else if(sdetail.getRangingWave()!=null &&sdetail.getRangingWave()>0 ){
			double df = getNeededPrecisionNumber(sdetail.getRangingWave()); 
			result.setRangingWave(df);
		}
		if(sdetail.getTravelingWave()!=null && sdetail.getTravelingWave()>0){
			double df = getNeededPrecisionNumber(sdetail.getTravelingWave()); 
			result.setTravellingWave(df);
		}
		if(StringUtils.isEmpty(sdetail.getReclosingSuccess())){
			result.setRecolse("");
		}else if("是".equals(sdetail.getReclosingSuccess())){
			result.setRecolse("成功");
		}else if("否".equals(sdetail.getReclosingSuccess())){
			result.setRecolse("失败");
		}else{
			result.setRecolse("不评价");
		}
		List<ProtectionEquipment> pelist = cm.listMainEquipmentsByStationIdAndprotectedId(sdetail.getStationId(), deviceId);
		//构建厂站保护信息
		List<ProtectInfo> list = buildProtectInfo(pelist,sdetail.getFaultReportMainProtectionActions(),deviceName,faultTime,sdetail.getStationName());
		String str = head_template.replace("#{station}", sdetail.getStationName()).replace("#{devicename}", deviceName);
		StringBuilder sb = new StringBuilder(str);
		for(ProtectInfo pi:list){
			if("主一保护".equals(pi.getProtectName())){
				if(sdetail.getManualFaultRangingFirst()!=null && sdetail.getManualFaultRangingFirst()>0){
					double df = getNeededPrecisionNumber(sdetail.getManualFaultRangingFirst()); 
					pi.setDistance(df);
				}else if(sdetail.getFaultRangingFirst()!=null && sdetail.getFaultRangingFirst()>0){
					double df = getNeededPrecisionNumber(sdetail.getFaultRangingFirst()); 
					pi.setDistance(df);
				}
			}else if("主二保护".equals(pi.getProtectName())){
				if(sdetail.getManualFaultRangingSecond()!=null && sdetail.getManualFaultRangingSecond()>0){
					double df = getNeededPrecisionNumber(sdetail.getManualFaultRangingSecond()); 
					pi.setDistance(df);
				}else if(sdetail.getFaultRangingSecond()!=null && sdetail.getFaultRangingSecond()>0){
					double df = getNeededPrecisionNumber(sdetail.getFaultRangingSecond()); 
					pi.setDistance(df);
				}
			}else if("主三保护".equals(pi.getProtectName())){
				if(sdetail.getManualFaultRangingThird()!=null && sdetail.getManualFaultRangingThird()>0){
					double df = getNeededPrecisionNumber(sdetail.getManualFaultRangingThird()); 
					pi.setDistance(df);
				}else if(sdetail.getFaultRangingThird()!=null && sdetail.getFaultRangingThird()>0){
					double df = getNeededPrecisionNumber(sdetail.getFaultRangingThird()); 
					pi.setDistance(df);
				}
			}
			//根据该厂站保护信息，设置厂站汇报信息
			str = acline_body_template.replace("#{protect}", pi.getProtectName());
			if(StringUtils.isNotEmpty(pi.getComponet())){
				str = str.replace("#{componet}", pi.getComponet());
			}
			if(StringUtils.isNotEmpty(pi.getPhase())){
				str = str.replace("#{phase}", pi.getPhase());
			}
			if(pi.getDistance()!=null && pi.getDistance()>0){
				str = str.replace("#{distance}", pi.getDistance()+"");
			}
			sb.append(str);
		}
		str = acline_footer_template;
		if(result.getTravellingWave()!=null){
			str = str.replace("#{travellingwave}", result.getTravellingWave()+"");
		}
		if(result.getRangingWave()!=null){
			str = str.replace("#{rangingwave}", result.getRangingWave()+"");
		}
		if(result.getRecolse()!=null){
			str = str.replace("#{reclose}", result.getRecolse());
		}
		sb.append(str);
		String content = sb.toString().replaceAll("#\\{[a-z]+\\}", " ");
		result.setContent(content);
		result.getProtectInfos().addAll(list);
		return result;
	}
	/**
	 * 构造保护动作信息
	 * @param lineId
	 * @param model
	 * @return
	 */
	private List<ProtectInfo> buildProtectInfo(List<ProtectionEquipment> pelist,Collection<FaultReportMainProtection> mains,String deviceName,Date faultTime,String stationName){
		List<ProtectInfo> result = new ArrayList<ProtectInfo>();
		List<ProtectInfo> pilist = getSFProtectReport(faultTime, deviceName, stationName);
		//构造本次保护动作模型
		for(ProtectionEquipment pe:pelist){
			ProtectInfo info = new ProtectInfo();
			info.setProtectName(pe.getType());
			for(ProtectInfo pi:pilist){
				if(pe.getName().equals(pi.getProtectName())){
					info.setComponet(pi.getComponet());
					info.setDistance(pi.getDistance());
					break;
				}
			}
			for(FaultReportMainProtection main:mains){
				if(!"trip".equals(main.getActionType())){
					continue;
				}
				if(pe.getId().equals(main.getProtectionId())){
					if(StringUtils.isEmpty(info.getPhase())){
						info.setPhase(main.getPhase());
					}else{
						info.setPhase(info.getPhase()+main.getPhase());
					}
				}
			}
			if(StringUtils.isNotEmpty(info.getPhase())){
				char[] str=info.getPhase().toCharArray();
				Arrays.sort(str);
				String phase = new String(str);
				info.setPhase(phase);
			}
			result.add(info);
		}
		return result;
	}
	
}
